package com.lqian.demo05;

import com.lqian.utils.SleepHelper;

/**
 * 线程的挂起和唤醒： Object.wait() 和 notify()/notifyAll()
 * 1. wait和notify/notifyAll方法只能用在同步代码块(synchronized)中
 *  why？
 *  wait和notify本质上其实是一种条件的竞争，至少来说，wait和notify方法一定是互斥存在的
 *  既然要实现互斥，那么synchronized就是一个很好的解决方法
 *  wait 和 notify是用于实现多个线程之间的通信，而通信必然会存在一个通信的载体。
 *  比如我们小时候玩游戏，用两个水杯，中间连一个线，然后可以实现较远距离的对话，这根线就是载体，
 *  那么在这里也是一样的，wait/notify是基于synchrnized来实现通信的。也就是两者必须要在同一个频道也就是同一个锁的范围内。
 * @author：Melody_LQ
 * @time：2022/8/22 6:56 下午
 */
public class WaitAndNotify {
    static int num = 0;

    public static void main(String[] args) {

        //声明一把锁
        final Object o = new Object();
        // 共享变量

        //线程A
        Thread A = new Thread(()->{

            //挂起阻塞
            try {
                synchronized (o){
                    for (int i = 0; i < 10; i++) {
                        System.out.println("A:" + num++);
                        o.wait();
                        o.notify();
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        A.start();
        // 主现场休眠一秒，确保线程A已经计算完成，阻塞在wait()方法
        SleepHelper.sleepSeconds(1);

        //唤醒线程A
        synchronized (o){
            for (int i = 0; i < 10; i++) {
                System.out.println("B:" + num++);
                try {
                    o.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                o.notify();
            }

        }


    }

}
